#include "Engine.h"
#include "Scene.h"
#include <iostream>
using namespace std;

class Window
{
	HWND hwnd;

public:
	Window(int width, int height)
	{
		WNDCLASSEX wc;
		ZeroMemory(&wc,sizeof(wc));
		wc.style=CS_HREDRAW|CS_VREDRAW;
		wc.lpfnWndProc=WndProc;
		wc.cbWndExtra=0;
		wc.cbClsExtra=0;
		wc.hInstance=GetModuleHandle(0);
		wc.hCursor=LoadCursor(0,IDC_ARROW);
		wc.hIcon=LoadIcon(0,IDI_APPLICATION);
		wc.lpszMenuName=NULL;
		wc.lpszClassName="Classs";
		wc.cbSize=sizeof(wc);

		RegisterClassEx(&wc);
		hwnd=CreateWindowEx(0,"Classs","RenderWindow",WS_OVERLAPPEDWINDOW,
			100,200,
			width,height,0,0,GetModuleHandle(0),0);
		UpdateWindow(hwnd);
		ShowWindow(hwnd,true);
	}

	HWND GetWindowHandle()
	{
		return hwnd;
	}

	static LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
	{
		switch(msg)
		{
		case WM_QUIT:
			DestroyWindow(hWnd);
			return 0;
		case WM_DESTROY:		
			PostQuitMessage(0);		
			return 0;
		default:
			return DefWindowProc(hWnd,msg,wp,lp);
		}
	}


};

Engine::Engine(int width, int height, int depth, bool windowed)
	:width(width), height(height)
{
	direct = Direct3DCreate9( D3D_SDK_VERSION );
	if( !direct )
		cout << "IDirect3D creating failed" << endl;

	D3DPRESENT_PARAMETERS d3dpp;
	if( depth == 32 )
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
		d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
	}
	else if( depth == 16 )
	{
		d3dpp.AutoDepthStencilFormat = D3DFMT_D15S1;
		d3dpp.BackBufferFormat = D3DFMT_A4R4G4B4;
	}
	else
	{
		cout << "Invalide depth format" << endl;
	}

	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferWidth = width;
	d3dpp.BackBufferHeight = height;
	d3dpp.EnableAutoDepthStencil = true;
	d3dpp.Flags = 0;
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	
	Window cwnd(width, height);
	wnd = cwnd.GetWindowHandle();
	d3dpp.hDeviceWindow = wnd;
	
	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dpp.MultiSampleQuality = 0;

	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.Windowed = windowed;

	direct->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd,D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp,&device);
	
	scene = new Scene(width, height, device);
}

Engine::~Engine()
{
	device->Release();
	direct->Release();
}

void Engine::SwapBuffers()
{
	MSG msg;
	if ( PeekMessage( &msg, wnd, 0, 0 ,true ) )
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	device->Present(0,0,0,0);
}

void Engine::Clear()
{
	device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff, 1.f, 0);
}

Scene* Engine::GetScene()
{
	return scene;
}